package com.bwie.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bwie.common.constants.JwtConstants;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.exception.BusinessException;
import com.bwie.common.pojo.dto.UserDto;
import com.bwie.common.pojo.po.UserPo;
import com.bwie.common.pojo.vo.ResponseUserTokenAndUserId;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import com.bwie.common.utils.MD5Utils;
import com.bwie.remote.AuthRemoteService;
import com.bwie.service.AuthService;
import lombok.SneakyThrows;
import org.apache.kafka.common.protocol.types.Field;
import org.redisson.Redisson;
import org.redisson.RedissonLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AuthRemoteService authRemoteService;
    @Autowired
    private Redisson redisson;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private KafkaTemplate<String,Object> kafkaTemplate;
    @SneakyThrows
    @Override
    public Result login(UserDto userDto) {
        //判断用户信息是否为空
        if(ObjectUtil.isEmpty(userDto)){
            //抛出异常
            throw new BusinessException(Result.error("数据不能为空"));
        }
        //调用远程服务进行登录
        Result<UserPo> login = authRemoteService.login(userDto);
        //kafka
        kafkaTemplate.send("authKafka", login.getData().getUsername());

        rabbitTemplate.convertAndSend("authMq",login.getData());
        //判断登录结果是否为空
        if(login.getData()==null){
            //抛出异常
            throw new BusinessException(Result.error("账号密码错误"));
        }
        //获取分布式锁
        RLock atuhLock = redisson.getLock("atuh_lock");
        //尝试获取锁，等待时间为5分钟
        boolean flag = atuhLock.tryLock(5, TimeUnit.MINUTES);
        try {
            //判断是否获取到锁
            if(flag){
                //获取用户id
                Integer userId = login.getData().getUserId();
                //获取角色id
                Result<List<Integer>> roleId = authRemoteService.getRoleId(userId);
                //存入角色id集合
                redisTemplate.opsForValue().set("login:role"+userId, roleId);
                //创建Hash
                HashMap<String, Object> hashMap = new HashMap<>();
                //生成userkey键
                String userKey = IdUtil.fastSimpleUUID();
                //添加userid
                hashMap.put(TokenConstants.LOGIN_TOKEN_KEY,userKey);
                //生成token
                String token = JwtUtils.createToken(hashMap);
                //存入redis
                redisTemplate.opsForValue().set(JwtConstants.USER_KEY+token,login.getData(),30, TimeUnit.MINUTES);
                //创建返回对象
                ResponseUserTokenAndUserId responseUserTokenAndUserId = new ResponseUserTokenAndUserId();
                //设置token
                responseUserTokenAndUserId.setToken(token);
                //设置用户信息
                responseUserTokenAndUserId.setUserPo(login.getData());
                responseUserTokenAndUserId.setRoleList(roleId.getData());
                //返回登录成功结果
                return Result.success(responseUserTokenAndUserId,"登录成功");
            }else {
                //抛出异常
                throw new BusinessException(Result.error("登录失败"));
            }
        }finally {
            //释放锁
            atuhLock.unlock();
        }
    }

    @SneakyThrows
    @Override
    public Result register(UserDto userDto) {
        // 将用户密码进行MD5加密
        String password = MD5Utils.md5(userDto.getPassword());
        // 将加密后的密码设置到用户对象中
        userDto.setPassword(password);
        // 调用远程服务进行注册
        authRemoteService.register(userDto);
        // 返回注册成功的消息
        return Result.success(null,"注册成功");
    }

    @SneakyThrows
    @Override
    public Result newLogin(UserDto userDto) {
        // 调用远程服务进行登录
        UserPo userPo = authRemoteService.newLogin(userDto);
        // 获取用户密码
        String password = userPo.getPassword();
        // 对密码进行MD5加密
        String newPassword = MD5Utils.md5(userDto.getPassword());
        // 判断用户输入的密码和加密后的密码是否一致
        if(!password.equals(newPassword)){
            // 如果不一致，抛出业务异常
            throw new BusinessException(Result.error("密码错误"));
        }
        // 如果一致，返回登录成功
        return Result.success(userPo,"登录成功");
    }
}
